package com.xw.unification.helper;

import org.springframework.util.StringUtils;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 字符串工具类, 仅包内可用
 *
 * @author qiwei
 * @date 2023-8-10 16:00:00
 * @since v1.0.0
 */
public class StringHelper {

    /**
     * 字符串是否有有效文本
     *
     * @param string 字符串内容
     * @return boolean
     */
    public static boolean hasText(String string) {
        return StringUtils.hasText(string);
    }

    /**
     * 字符串是否为空
     *
     * @param string 字符串内容
     * @return boolean
     */
    public static boolean isEmpty(String string) {
        return string != null && !"".equals(string);
    }

    /**
     * 字符串是否为空白
     *
     * @param string 字符串内容
     * @return boolean
     */
    public static boolean isBlank(String string) {
        return !StringUtils.hasText(string);
    }

    /**
     * 拼接 url, urlPathFragments = null 或没有有效内容时返回 null
     *
     * @param urlPathFragments  url fragments
     * @return String
     */
    public static String concatUrl(String... urlPathFragments) {
        if (urlPathFragments == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        boolean lastHasSlash = false;
        boolean hasSlash = false;
        for (String fragment : urlPathFragments) {
            if (fragment == null || fragment.length() <= 0) {
                continue;
            }
            for (int i = 0; i < fragment.length(); i++) {
                char ch = fragment.charAt(i);
                if (ch == ' ') {
                    // jump to next char
                    continue;
                } else if (ch == '/') {
                    hasSlash = true;
                    if (!lastHasSlash) {
                        builder.append(ch);
                    }
                } else {
                    if (lastHasSlash) {
                        lastHasSlash = false;
                    }
                    if (hasSlash) {
                        hasSlash = false;
                    }
                    builder.append(ch);
                }
            }
            lastHasSlash = hasSlash;
            hasSlash = false;
        }
        return builder.length() <= 0 ? null : builder.toString();
    }

    /**
     * 解析 uri 的 query 参数, 返回有序 map
     * @param uri   URI String
     * @return  LinkedHashMap&lt;String, LinkedHashSet&lt;String&gt;&gt;
     */
    public static LinkedHashMap<String, Set<String>> parseQueryParams(String uri, boolean encoded) {
        try {
            if (!hasText(uri)) {
                throw new URISyntaxException(uri, "URI is blank");
            }
            return parseQueryParams(URI.create(uri), encoded);
        } catch (URISyntaxException e) {
            throw new RuntimeException("URI syntax is not matched", e);
        }
    }

    /**
     * 解析 uri 的 query 参数, 返回有序 map
     * @param uri   URI
     * @return  LinkedHashMap&lt;String, LinkedHashSet&lt;String&gt;&gt;
     */
    public static LinkedHashMap<String, Set<String>> parseQueryParams(URI uri, boolean encoded) {
        LinkedHashMap<String, Set<String>> map = new LinkedHashMap<>();
        if (uri == null) {
            return map;
        }
        String query = encoded ? uri.getQuery() : uri.getRawQuery();
        if (query == null) {
            return map;
        }
        StringBuilder keyBuilder = new StringBuilder();
        StringBuilder valueBuilder = new StringBuilder();
        StringBuilder builder = keyBuilder;
        String key;
        Set<String> valueSet;
        char ch;
        for (int i = 0; i < query.length(); i++) {
            ch = query.charAt(i);
            if (ch == '&') {
                if (keyBuilder.length() > 0) {
                    key = keyBuilder.toString();
                    valueSet = map.getOrDefault(key, new LinkedHashSet<>());
                    valueSet.add(valueBuilder.toString());
                    map.put(key, valueSet);
                    keyBuilder.delete(0, keyBuilder.length());
                    valueBuilder.delete(0, valueBuilder.length());
                }
                builder = keyBuilder;
            } else if (ch == '=' && valueBuilder.length() == 0) {
                builder = valueBuilder;
            } else if (builder != null) {
                builder.append(ch);
            }
        }
        if (keyBuilder.length() > 0) {
            key = keyBuilder.toString();
            valueSet = map.getOrDefault(key, new LinkedHashSet<>());
            valueSet.add(valueBuilder.toString());
            map.put(key, valueSet);
        }
        return map;
    }

}
